/**
 * 封装HTTP请求类
 */
class WeappRequest {
  //同时发送请求的次数，私有变量
  #requestCount;
  //实例属性，用于设置默认请求参数
  defaults = {
    baseUrl: '', //请求基准地址
    url: '', //每个请求的路径
    data: null, //请求的数据
    method: "GET", //请求方法
    header: {
      "Content-Type": "application/json"
    },
    timeout: 60000, //默认的超时时长，为1分钟(60秒)
    isLoading: true //是否显示loading
  }

  //定义拦截器对象。方便请求之前和响应之后进行逻辑处理。
  interceptors = {
    //请求拦截器，在请求发送之前，对请求参数进行修改
    request: config => config,
    //响应拦截器，在请求响应之后，对输出进行修改。
    response: response => response
  }

  //构造函数
  constructor(option) {
    this.defaults = Object.assign({}, this.defaults, option);
    this.#requestCount = 0;
  }
  /**
   * 请求HTTP传输
   * @param {Object} options 请求的参数
   */
  request(options) {
    options.url = this.defaults.baseUrl + options.url;
    //合并参数
    options = { ...this.defaults, ...options };

    //显示等待
    options.isLoading && options.method !== "UPLOAD" && this.#requestCount++ == 0 && wx.showLoading();
    delete options.baseUrl;

    //请求之前调用拦截器
    this.interceptors.request(options);

    //发送请求
    return new Promise((resolve, reject) => {
      if (options.method === "UPLOAD") {
        wx.uploadFile({
          ...options,
          success: res => {
            this.interceptors.response(Object.assign({}, res, { config: options, success: true }));
            resolve(res);
          },
          fail: err => {
            this.interceptors.response(Object.assign({}, err, { config: options, success: false }));
            reject(err);
          }
        })
      }
      else {
        wx.request({
          ...options,
          success: res => {
            this.interceptors.response(Object.assign({}, res, { config: options, success: true }));
            resolve(res);
          },
          fail: err => {
            this.interceptors.response(Object.assign({}, err, { config: options, success: false }));
            reject(err);
          },
          complete: () => options.isLoading && --this.#requestCount == 0 && wx.hideLoading()
        })
      }
    });
  }

  get(url, data = {}, config) {
    return this.request(Object.assign({ url, data, method: "GET" }, config));
  }
  post(url, data = {}, config) {
    return this.request(Object.assign({ url, data, method: "POST" }, config))
  }
  put(url, data = {}, config) {
    return this.request(Object.assign({ url, data, method: "PUT" }, config))
  }
  delete(url, data = {}, config) {
    return this.request(Object.assign({ url, data, method: "DELETE" }, config));
  }

  /**
   * 同时发起所有的Promise请求。
   * @param  {...any} promise Promise对象
   */
  all(...promise) {
    return Promise.all(promise);
  }

  /**
   * 向指定服务器上传文件。
   * @param {String} url 上传文件的服务器地址
   * @param {String} filePath 上传文件的本地临时地址
   * @param {String} name 上传文件的名称
   * @param {Object} config 要传递的其它配置项
   */
  upload(url, filePath, name = 'file', config) {
    return this.request(Object.assign({ url, filePath, name, method: "UPLOAD" }, config));
  }
}

export default WeappRequest;